#include "Order.h"
#include <iostream>
#include <vector>




/// Comparision criterion
bool same_source(const IndividualOption & a, const IndividualOption & b)
{
  return (a.from==b.from);
}

/// sort criterion
bool by_src_and_decreasing_weight(const IndividualOption & a, const IndividualOption & b)
{
  return (a.from<b.from) or ((a.from == b.from) and (a.w>b.w));
}

/// comparision criterion
bool same_dest(const IndividualOption & a, const IndividualOption & b)
{
  return a.to==b.to;
}

/// sort criterion
bool by_dest_and_decreasing_weight(const IndividualOption & a, const IndividualOption & b)
{
  return (a.to<b.to) or ((a.to == b.to) and (a.w>b.w));
}


/// normalization action
void normalize_action(std::list<IndividualOption>::iterator first, std::list<IndividualOption>::iterator last)
{
  double Z = 0;
  for(std::list<IndividualOption>::iterator i = first; i!=last; ++i)
    Z+= fabs(i->w);
  if (Z)
  {
      for(std::list<IndividualOption>::iterator i = first; i!=last; ++i)
        i->w /= Z;
  }
}



void 
Order::proposeMove(State & s, const Location &from, const Location &to, int direction, double w)
{
  IndividualOption opt;
  opt.from = from;
  opt.to = to;
  opt.direction = direction;
  opt.w = w;
  push_back(opt);
}

void 
Order::execute(State & s, bool simulation)
{

    s.bug << "* before selection" << std::endl;
    s.bug << *this << std::endl;

    // removes incompatible options
    solve_conflicts();

    s.bug << "* after removing conflicts" << std::endl;
    s.bug << *this << std::endl;

    select_best();

    s.bug << "* after selecting best" << std::endl;
    s.bug << *this << std::endl;

  //if(conf>0) s.bug << "conflicts: " << conf << std::endl;

  // the order is now a 'valid' order in my sense
  // but NOT in the organizers sense:
  // i.e. no pair of ants goes to the same location
  // BUT: they may collide with orgiginal positions!!!

  // remove 'no move' orders
  iterator it=begin();
  while( it != end() )
    {
      if (( it->direction) == -1)
	{ // no move
	  it=erase(it);
	}
      else
	{
	  it++;
	}
    }

  // iterate orders until possibles
  unsigned previous_size;
  do
    {
      previous_size = size();
      s.bug << "solving conflicts" << std::endl;
      it = begin();
      while(it!=end())
	{
          if(s.location(it->to).ant == -1)
	    { // valid move
	      // TU experiment : try to combine battle resolution with move scheduling
	      unsigned enemies_killed;
	      bool I_die = will_die(s, it->to, enemies_killed);
	      if(!I_die or enemies_killed>1)
		{
		  if(simulation)
		    s.simulateMove(it->from, it->to);
		  else
		    s.makeMove(it->from, it->direction);
		  it=erase(it);
		}
	    }
	  else
	    { // not possible YET
	      ++it;
	    }
	}
    }
  while(previous_size > size());

}


/* dump for debug */
std::ostream& operator<<(std::ostream &os, const Order &order)
{
    for (Order::const_iterator it=order.begin(); it != order.end(); ++it)
    {
        os << it->w << "." << "("
              << it->from.col << "," << it->from.row << ") -> ("
              << it->to.col << "," << it->to.row << ")";
        if (it->direction>=0)
            os << " [" << CDIRECTIONS[it->direction] << "]";
        else
            os << " [-]";
        os << std::endl;
    }
}


	
	
